#!/usr/bin/perl

use strict;
use warnings;

use utf8;
use Getopt::Long;
use Net::OpenSSH;    # For now, it seems to be the way to go, nice tool
use Pod::Usage;

###############################################################################
# G L O B  V A R S
###############################################################################

my $optLocal;        # If set, the local environment will be examined
my $optHost;         # The target host
my $optUser;         # Username for use with ssh
my $optOutFile;      # The name of the ouput file
my $optFormat;       # The output format: txt or latex
my $optHmc;
my $optHmcUser;
my @optVios;         # it's an array, because multiple VIO servers may exist
my $optVerbose;
my $optHelp;
my $optManual;

my $os;              # OS "aix" "linux" "MSWin32"...
my $sshHost;         # The SSH connection to the target host
my %sshOpts;         # Hash to hole optional params for ths SSH connections
my $sshHmc;          # The SSH connection to the HMC
my @sshVios;         # Array of ssh connections to the VIO servers

###############################################################################
# S U B R O U T I N E S
###############################################################################

sub initialChecker
{

    # check if we're at the right place with the right parms
    $os = "$^O";     # "aix" "linux" "MSWin32"...
    if ($optHost)
    {

        # there should only be exactly one host
        &hostChecker( $optHost, $optUser, "host" );
    }

    if ($optHmc)
    {

        # there should be exactly zero or one HMC
        &hostChecker( $optHmc, $optHmcUser, "hmc" );
    }

    my $s_optVios = @optVios;
    if ( $s_optVios > 0 )
    {

        # there should be zero or more VIOS's
        foreach (@optVios)
        {
            my ($vios) = $_;
            &hostChecker( $vios, "padmin", "vio" );
        }
    }
}

sub hostChecker
{

    # $host: host name or IP address, $hostType: one of host, hmc, or vio
    # checks that re independent of $hostType
    my ( $host, $user, $hostType ) = @_;
    &printV("Checking \"$host\" with user \"$user\" as host type \"$hostType\"...\n");
    %sshOpts = (
                 'user'    => $user,
                 'timeout' => 15
               );
    &printV("Remote user is $user.\n");

    # $hostType-dependent checks
    if ( $hostType eq "host" )
    {
        $sshHost = Net::OpenSSH->new( $host, %sshOpts );
        $sshHost->error
          and die "Couldn't establish SSH connection: " . $sshHost->error;
        &printV("SSH connection established.\n");
        my ( $uname, $err ) = $sshHost->capture2("uname");
        $sshHost->error
          and die "Remote system is not AIX or remote command execution failed.";
        chomp($uname);
        &printV("Remote system is $uname.\n");
        unless ( $uname eq "AIX" )
        {
            die "Remote system is not AIX. Exiting...";
        }
    }
    elsif ( $hostType eq "hmc" )
    {
        $sshHmc = Net::OpenSSH->new( $host, %sshOpts );
        $sshHmc->error
          and die "Couldn't establish SSH connection: " . $sshHmc->error;
        &printV("SSH connection established.\n");
        my @out = $sshHmc->capture("lshmc -v");
        $sshHmc->error
          and die "Remote system is not an HMC or remote command execution failed.";
        my @result = grep ( /\*DS Hardware Management Console/, @out );
        my $s_result = @result;
        if ( $s_result != 1 ) { die "$host is not an HMC. Exiting..."; }
        &printV("Remote system is an HMC.\n");
    }
    elsif ( $hostType eq "vio" )
    {
        my $s_sshVios = @sshVios;
        $sshVios[$s_sshVios] = Net::OpenSSH->new( $host, %sshOpts );
        $sshVios[$s_sshVios]->error
          and die "Couldn't establish SSH connection: " . $sshVios[$s_sshVios]->error;
        &printV("SSH connection established.\n");
        my @out = $sshVios[$s_sshVios]->capture("ioscli ioslevel");
        $sshVios[$s_sshVios]->error
          and die "Remote system is not a VIO server or remote command execution failed.";
        &printV("Remote system is a VIO server.\n");
    }
}

sub director
{

    # Will check where and how to run collector commands and direct them to the right place
}

sub formatter
{

    # Will format output
    if ( $optFormat eq "latex" )
    {

        # Generate LaTeX output
    }
    else
    {

        # Generate plain txt output
    }
}

sub stats
{

    # Will provide statistics about the collection process
}

sub printV
{

    # Verbose print
    my ($msg) = @_;
    print "+ " . $msg if ($optVerbose);
}

sub theEnd
{

    # When this one is called, it's over, pal...
}

###############################################################################
# M A I N
###############################################################################

# +--------------------+
# | Options processing |
# +--------------------+

GetOptions(
            'host=s'    => \$optHost,
            'user=s'    => \$optUser,
            'local'     => \$optLocal,
            'out=s'     => \$optOutFile,
            'format=s'  => \$optFormat,
            'hmc=s'     => \$optHmc,
            'hmcuser=s' => \$optHmcUser,
            'vio=s'     => \@optVios,
            'verbose!'  => \$optVerbose,
            'help'      => \$optHelp,
            'manual'    => \$optManual
          );

if ($optManual)
{
    pod2usage( {-verbose => 2, -exitval => 0} );
}

if ($optHelp)
{
    pod2usage( {-verbose => 1, -exitval => 0} );
}

if ( $optHost && $optLocal )
{
    my $msg = "Options --host and --local are mutually exclusive.";
    pod2usage( {-verbose => 1, -exitval => 0, -message => "$msg\n"} );
}

if ( $optLocal && $optUser )
{

    # If both are specified, it means you want to discover the local machine using a different user
    $optHost = "localhost";
    &printV(
        "Both --user and --local are specified, the local host will be discovered using user $optUser.\n"
    );
}

if ( $optHost && !$optUser )
{

    #my $msg = "Option --host requires option --user.";
    #pod2usage({-verbose => 1, -exitval => 0, -message => "$msg\n"});
    $optUser = getlogin();
    &printV("Option --user was not provided, local username $optUser will be used\n");
}

if ( $optUser && !$optHost )
{
    my $msg = "Option --user makes no sense without option --host.";
    pod2usage( {-verbose => 1, -exitval => 0, -message => "$msg\n"} );
}

if (    ( defined $optFormat )
     && ( $optFormat ne "latex" )
     && ( $optFormat ne "txt" ) )
{
    my $msg = "Unsupported format: $optFormat";
    pod2usage( {-verbose => 1, -exitval => 1, -message => "$msg\n"} );
}

&printV("Options checked.\n");

&initialChecker;

&theEnd;

__END__

=head1 NAME

pc.pl - POWER Collector

=head1 SYNOPSIS

=head1 DESCRIPTION

=head1 OPTIONS

=head1 EXIT STATUS

=head1 EXAMPLES

=head1 AUTHOR

soos.zoltan@gmail.com

=cut
